// // // // tools/audit-gm/audit-seal-daemon.c
// // // #define _GNU_SOURCE
// // // #include <stdio.h>
// // // #include <stdlib.h>
// // // #include <unistd.h>
// // // #include <sys/inotify.h>
// // // #include <sys/stat.h>
// // // #include <fcntl.h>
// // // #include <errno.h>
// // // #include <string.h>

// // // #include <openssl/evp.h>
// // // #include <openssl/pkcs12.h>
// // // #include <openssl/x509.h>
// // // #include <openssl/err.h>
// // // #include <openssl/bio.h>
// // // #include <openssl/buffer.h>

// // // #include "alarm.c"            // 你已有的报警实现
// // // #include "../../lib/gm_crypto.h"  // 你已有的 GM 封装

// // // #define SM2_ID "1234567812345678"
// // // #define P12_PATH "/etc/pki/audit/sm2.p12"
// // // #define SALT_PATH "/etc/pki/audit/p12_salt"
// // // #define SALT_BYTES 16
// // // #define DERIVE_BYTES 32
// // // #define DERIVE_ITERATIONS 200000

// // // static void die(const char *m){ perror(m); exit(1); }
// // // static void diee(const char *m){ fprintf(stderr,"%s\n",m); exit(1); }

// // // static int read_salt_hexfile(const char *path, unsigned char *out, size_t outlen){
// // //     FILE *f=fopen(path,"r"); if(!f) return -1;
// // //     char buf[256]; if(!fgets(buf,sizeof(buf),f)){ fclose(f); return -1; }
// // //     fclose(f);
// // //     size_t len=strlen(buf); while(len&&(buf[len-1]=='\n'||buf[len-1]=='\r')) buf[--len]=0;
// // //     if (len/2 != outlen) return -1;
// // //     for (size_t i=0;i<outlen;i++){ unsigned int hi,lo;
// // //         if (sscanf(&buf[i*2], "%1x%1x", &hi,&lo)!=2) return -1;
// // //         out[i] = (hi<<4) | lo;
// // //     }
// // //     return 0;
// // // }

// // // static void hexdump(const unsigned char *buf, size_t len, char *out, size_t outlen){
// // //     static const char hex[]="0123456789abcdef";
// // //     if (outlen < len*2+1) return;
// // //     for (size_t i=0;i<len;i++){ out[i*2]=hex[(buf[i]>>4)&0xF]; out[i*2+1]=hex[buf[i]&0xF]; }
// // //     out[len*2]=0;
// // // }

// // // static int derive_pass(const char *secret, const unsigned char *salt, int saltlen,
// // //                        int iter, unsigned char *out, int outlen)
// // // {
// // //     const EVP_MD *md = EVP_get_digestbyname("sm3");
// // //     if (!md) diee("[ERROR] OpenSSL 无 sm3");
// // //     return PKCS5_PBKDF2_HMAC(secret, strlen(secret), salt, saltlen, iter, md, outlen, out) ? 0 : -1;
// // // }

// // // static int load_p12(const char *p12_path, const char *passhex, EVP_PKEY **out_pkey, X509 **out_cert){
// // //     FILE *f=fopen(p12_path,"rb"); if(!f) return -1;
// // //     PKCS12*p12 = d2i_PKCS12_fp(f,NULL); fclose(f);
// // //     if(!p12) return -1;
// // //     EVP_PKEY*k=NULL; X509*c=NULL;
// // //     if (!PKCS12_parse(p12, passhex, &k, &c, NULL)){ PKCS12_free(p12); return -1; }
// // //     PKCS12_free(p12);
// // //     *out_pkey=k; *out_cert=c; return 0;
// // // }

// // // /* 计算某行的SM3（含换行） */
// // // static int sm3_line(const char *line, size_t n, unsigned char out32[32]){
// // //     const EVP_MD* sm3 = EVP_get_digestbyname("sm3");
// // //     if (!sm3) return -1;
// // //     unsigned int mdlen=0;
// // //     EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if (!ctx) return -1;
// // //     if (EVP_DigestInit_ex(ctx, sm3, NULL)!=1 ||
// // //         EVP_DigestUpdate(ctx, line, n)!=1 ||
// // //         EVP_DigestFinal_ex(ctx, out32, &mdlen)!=1 || mdlen!=32){
// // //         EVP_MD_CTX_free(ctx); return -1;
// // //     }
// // //     EVP_MD_CTX_free(ctx); return 0;
// // // }

// // // /* 计算chain: H1=SM3( H0 || line1 ); H2=SM3( H1 || line2)...
// // //  * 其中H0=0x00..00
// // //  * 同时生成 .idx 文件: i=N off=xxx lhash=<hex> chash=<hex>
// // //  */
// // // static int build_index_and_chain(const char *log_path,
// // //                                  const char *idx_path,
// // //                                  unsigned long long *out_lines,
// // //                                  unsigned char out_chain32[32])
// // // {
// // //     FILE *lf = fopen(log_path,"rb");
// // //     if (!lf) return -1;
// // //     FILE *ix = fopen(idx_path, "w");
// // //     if (!ix){ fclose(lf); return -1; }

// // //     unsigned char H[32]={0};
// // //     unsigned long long ln=0;
// // //     unsigned long long off=0;

// // //     fprintf(ix, "# audit idx v1\n");
// // //     fprintf(ix, "# file=%s\n", log_path);

// // //     char *line=NULL;
// // //     size_t cap=0;
// // //     ssize_t n;
// // //     static const char hex[]="0123456789abcdef";
// // //     while ((n = getline(&line, &cap, lf)) != -1){
// // //         ln++;
// // //         /* lhash */
// // //         unsigned char L[32];
// // //         if (sm3_line(line,(size_t)n,L)!=0){ free(line); fclose(lf); fclose(ix); return -1; }

// // //         /* chash = SM3(H || line) */
// // //         unsigned int mdlen=0;
// // //         EVP_MD_CTX *ctx=EVP_MD_CTX_new(); if(!ctx){free(line);fclose(lf);fclose(ix);return -1;}
// // //         if (EVP_DigestInit_ex(ctx, EVP_get_digestbyname("sm3"), NULL)!=1 ||
// // //             EVP_DigestUpdate(ctx, H, sizeof(H))!=1 ||
// // //             EVP_DigestUpdate(ctx, line, (size_t)n)!=1 ||
// // //             EVP_DigestFinal_ex(ctx, H, &mdlen)!=1 || mdlen!=32){
// // //             EVP_MD_CTX_free(ctx); free(line); fclose(lf); fclose(ix); return -1;
// // //         }
// // //         EVP_MD_CTX_free(ctx);

// // //         /* 转 hex */
// // //         char Lhex[65], Hhex[65];
// // //         for (int i=0;i<32;i++){ Lhex[i*2]=hex[(L[i]>>4)&0xF]; Lhex[i*2+1]=hex[L[i]&0xF]; }
// // //         Lhex[64]=0;
// // //         for (int i=0;i<32;i++){ Hhex[i*2]=hex[(H[i]>>4)&0xF]; Hhex[i*2+1]=hex[H[i]&0xF]; }
// // //         Hhex[64]=0;

// // //         /* off 是行首偏移(上一行结束offset) */
// // //         fprintf(ix, "i=%llu off=%llu lhash=%s chash=%s\n",
// // //                 ln, off, Lhex, Hhex);

// // //         off = (unsigned long long)ftell(lf);
// // //     }
// // //     free(line);
// // //     fclose(lf);
// // //     fclose(ix);

// // //     *out_lines = ln;
// // //     memcpy(out_chain32,H,32);
// // //     return 0;
// // // }

// // // /* 追加模式：从当前文件偏移开始读新行，更新 idx 和 chain */
// // // static int append_index_and_chain(const char *log_path, const char *idx_path,
// // //                                   unsigned long long *io_lines,
// // //                                   unsigned char io_chain32[32],
// // //                                   unsigned long long *io_offset)
// // // {
// // //     FILE *lf = fopen(log_path, "rb");
// // //     if(!lf) return -1;
// // //     FILE *ix = fopen(idx_path, "a");
// // //     if(!ix){ fclose(lf); return -1; }

// // //     if (fseek(lf, (long)(*io_offset), SEEK_SET)!=0){ fclose(lf); fclose(ix); return -1; }

// // //     char *line=NULL; size_t cap=0; ssize_t n;
// // //     static const char hex[]="0123456789abcdef";
// // //     while ((n = getline(&line,&cap,lf)) != -1){
// // //         (*io_lines)++;
// // //         /* lhash */
// // //         unsigned char L[32];
// // //         if (sm3_line(line,(size_t)n,L)!=0){ free(line); fclose(lf); fclose(ix); return -1; }

// // //         /* chash = SM3(H || line) */
// // //         unsigned int mdlen=0;
// // //         EVP_MD_CTX *ctx=EVP_MD_CTX_new(); if(!ctx){free(line);fclose(lf);fclose(ix);return -1;}
// // //         if (EVP_DigestInit_ex(ctx, EVP_get_digestbyname("sm3"), NULL)!=1 ||
// // //             EVP_DigestUpdate(ctx, io_chain32, 32)!=1 ||
// // //             EVP_DigestUpdate(ctx, line, (size_t)n)!=1 ||
// // //             EVP_DigestFinal_ex(ctx, io_chain32, &mdlen)!=1 || mdlen!=32){
// // //             EVP_MD_CTX_free(ctx); free(line); fclose(lf); fclose(ix); return -1;
// // //         }
// // //         EVP_MD_CTX_free(ctx);

// // //         /* 转 hex */
// // //         char Lhex[65], Hhex[65];
// // //         for(int i=0;i<32;i++){ Lhex[i*2]=hex[(L[i]>>4)&0xF]; Lhex[i*2+1]=hex[L[i]&0xF]; }
// // //         Lhex[64]=0;
// // //         for(int i=0;i<32;i++){ Hhex[i*2]=hex[(io_chain32[i]>>4)&0xF]; Hhex[i*2+1]=hex[io_chain32[i]&0xF]; }
// // //         Hhex[64]=0;

// // //         fprintf(ix, "i=%llu off=%llu lhash=%s chash=%s\n",
// // //                 *io_lines, *io_offset, Lhex, Hhex);
// // //         *io_offset = (unsigned long long)ftell(lf);
// // //     }
// // //     free(line);
// // //     fclose(lf);
// // //     fclose(ix);
// // //     return 0;
// // // }

// // // /* 对 idx 文件做 sm3 */
// // // static int sm3_file_hex(const char *path, char out_hex[65]){
// // //     FILE *f=fopen(path,"rb"); if(!f) return -1;
// // //     const EVP_MD* sm3=EVP_get_digestbyname("sm3");
// // //     if(!sm3){ fclose(f); return -1; }
// // //     EVP_MD_CTX* ctx=EVP_MD_CTX_new(); if(!ctx){ fclose(f); return -1; }
// // //     if(EVP_DigestInit_ex(ctx, sm3, NULL)!=1){ EVP_MD_CTX_free(ctx); fclose(f); return -1; }
// // //     unsigned char buf[4096]; size_t n;
// // //     while( (n=fread(buf,1,sizeof(buf),f)) > 0){
// // //         if (EVP_DigestUpdate(ctx, buf, n)!=1){ EVP_MD_CTX_free(ctx); fclose(f); return -1; }
// // //     }
// // //     fclose(f);
// // //     unsigned char md[32]; unsigned int mdlen=0;
// // //     if(EVP_DigestFinal_ex(ctx, md,&mdlen)!=1 || mdlen!=32){ EVP_MD_CTX_free(ctx); return -1; }
// // //     EVP_MD_CTX_free(ctx);
// // //     static const char hex[]="0123456789abcdef";
// // //     for(int i=0;i<32;i++){ out_hex[i*2]=hex[(md[i]>>4)&0xF]; out_hex[i*2+1]=hex[md[i]&0xF]; }
// // //     out_hex[64]=0;
// // //     return 0;
// // // }

// // // /* 生成/更新 seal 文件 */
// // // static int write_seal(const char *log_path,
// // //                       unsigned long long lines,
// // //                       const unsigned char chain[32],
// // //                       const char *index_sm3_hex,
// // //                       EVP_PKEY *pkey, X509 *cert)
// // // {
// // //     // canon
// // //     char chain_hex[65];
// // //     hexdump(chain, 32, chain_hex, sizeof(chain_hex));

// // //     char *canon=NULL;
// // //     if (asprintf(&canon,
// // //         "version=1\n"
// // //         "hash=sm3\n"
// // //         "sign=sm2\n"
// // //         "sm2_id=%s\n"
// // //         "path=%s\n"
// // //         "records=%llu\n"
// // //         "chain=%s\n"
// // //         "key_fpr=", SM2_ID, log_path, (unsigned long long)lines, chain_hex) < 0) return -1;

// // //     // fingerprint SM3
// // //     unsigned char *der=NULL; int derlen=i2d_X509(cert,&der);
// // //     if (derlen<=0){ free(canon); return -1; }
// // //     unsigned char md[EVP_MAX_MD_SIZE]; unsigned int mdlen=0;
// // //     EVP_MD_CTX *ctx=EVP_MD_CTX_new(); if(!ctx){ free(canon); OPENSSL_free(der); return -1; }
// // //     if (EVP_DigestInit_ex(ctx, EVP_get_digestbyname("sm3"), NULL)!=1 ||
// // //         EVP_DigestUpdate(ctx, der, derlen)!=1 ||
// // //         EVP_DigestFinal_ex(ctx, md, &mdlen)!=1){
// // //         EVP_MD_CTX_free(ctx); free(canon); OPENSSL_free(der); return -1;
// // //     }
// // //     EVP_MD_CTX_free(ctx);
// // //     char fpr_hex[65];
// // //     for(unsigned i=0;i<mdlen;i++){
// // //         static const char hex[]="0123456789abcdef";
// // //         fpr_hex[i*2]=hex[(md[i]>>4)&0xF];
// // //         fpr_hex[i*2+1]=hex[md[i]&0xF];
// // //     }
// // //     fpr_hex[mdlen*2]=0;

// // //     // canon 拼接 key_fpr + index_sm3
// // //     char *canon2=NULL;
// // //     if (asprintf(&canon2, "%s%s\nindex_sm3=%s\n", canon, fpr_hex, index_sm3_hex)<0){
// // //         free(canon); OPENSSL_free(der); return -1;
// // //     }
// // //     free(canon);

// // //     // sign canon2
// // //     unsigned char *sig=NULL; size_t siglen=0;
// // //     if (gm_sm2_sign(pkey, (const unsigned char*)canon2, strlen(canon2), SM2_ID, &sig, &siglen)!=0){
// // //         free(canon2); OPENSSL_free(der); return -1;
// // //     }

// // //     // cert der to b64
// // //     char *cert_b64 = NULL;
// // //     {
// // //         BIO *b64=BIO_new(BIO_f_base64());
// // //         BIO *mem=BIO_new(BIO_s_mem());
// // //         if(!b64||!mem){ if(b64)BIO_free(b64); if(mem)BIO_free(mem); free(canon2); OPENSSL_free(der); OPENSSL_free(sig); return -1; }
// // // #ifdef BIO_FLAGS_BASE64_NO_NL
// // //         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// // // #endif
// // //         BIO_push(b64, mem);
// // //         (void)BIO_write(b64, der, derlen);
// // //         (void)BIO_flush(b64);
// // //         BUF_MEM*bptr=NULL; BIO_get_mem_ptr(b64,&bptr);
// // //         cert_b64 = malloc(bptr->length+1);
// // //         memcpy(cert_b64, bptr->data, bptr->length);
// // //         cert_b64[bptr->length]=0;
// // //         BIO_free_all(b64);
// // //     }
// // //     OPENSSL_free(der);

// // //     // sig to b64
// // //     char *sig_b64=NULL;
// // //     {
// // //         BIO *b64=BIO_new(BIO_f_base64());
// // //         BIO *mem=BIO_new(BIO_s_mem());
// // //         if(!b64||!mem){ if(b64)BIO_free(b64); if(mem)BIO_free(mem); free(cert_b64); free(canon2); OPENSSL_free(sig); return -1; }
// // // #ifdef BIO_FLAGS_BASE64_NO_NL
// // //         BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// // // #endif
// // //         BIO_push(b64,mem);
// // //         (void)BIO_write(b64, sig, siglen);
// // //         (void)BIO_flush(b64);
// // //         BUF_MEM*bptr=NULL; BIO_get_mem_ptr(b64,&bptr);
// // //         sig_b64 = malloc(bptr->length+1);
// // //         memcpy(sig_b64, bptr->data, bptr->length);
// // //         sig_b64[bptr->length]=0;
// // //         BIO_free_all(b64);
// // //     }
// // //     OPENSSL_free(sig);

// // //     // write seal
// // //     char *seal_path=NULL;
// // //     if (asprintf(&seal_path, "%s.seal", log_path)<0){
// // //         free(cert_b64); free(sig_b64); free(canon2); return -1;
// // //     }
// // //     FILE *sf = fopen(seal_path, "w");
// // //     if(!sf){ free(cert_b64); free(sig_b64); free(canon2); free(seal_path); return -1; }

// // //     fprintf(sf, "# audit-seal v1 (SM2/SM3)\n%s", canon2);
// // //     fprintf(sf, "cert_der_base64=%s\nsig_base64=%s\n", cert_b64, sig_b64);
// // //     fclose(sf);
// // //     chmod(seal_path,0600);

// // //     free(seal_path); free(cert_b64); free(sig_b64); free(canon2);
// // //     return 0;
// // // }

// // // /* 主流程：给定 log_path，建立 idx/链值；监听变更 */
// // // int main(int argc, char **argv)
// // // {
// // //     if (argc!=2){
// // //         fprintf(stderr,"Usage: %s /var/log/audit/audit.log\n", argv[0]);
// // //         return 1;
// // //     }
// // //     const char *log_path = argv[1];

// // //     OpenSSL_add_all_algorithms();
// // //     ERR_load_crypto_strings();
// // //     if (gm_crypto_init()!=0) diee("gm init failed");

// // //     // 派生P12口令
// // //     unsigned char salt[SALT_BYTES];
// // //     if (read_salt_hexfile(SALT_PATH, salt, sizeof(salt))!=0) diee("read salt failed");
// // //     char *secret = getpass("Enter master passphrase (for P12): ");
// // //     if(!secret||!*secret) diee("empty passphrase");
// // //     unsigned char derived[DERIVE_BYTES];
// // //     if (derive_pass(secret, salt, sizeof(salt), DERIVE_ITERATIONS, derived, sizeof(derived))!=0) diee("PBKDF2 failed");
// // //     char passhex[DERIVE_BYTES*2+1]; hexdump(derived,sizeof(derived),passhex,sizeof(passhex));
// // //     OPENSSL_cleanse(secret, strlen(secret));

// // //     // Load key/cert
// // //     EVP_PKEY *pkey=NULL; X509* cert=NULL;
// // //     if (load_p12(P12_PATH, passhex, &pkey, &cert)!=0) diee("load p12 failed");
// // //     EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
// // //     if (!eckey || EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey))!=NID_sm2) diee("not SM2 key");

// // //     // 构造 idx_path
// // //     char *idx_path=NULL;
// // //     if (asprintf(&idx_path, "%s.idx", log_path)<0) diee("asprintf");

// // //     // 先全量扫描 & 生成 idx & chain
// // //     unsigned long long lines=0; unsigned char chain[32];
// // //     if (access(idx_path, F_OK)!=0){
// // //         // 不存在，则新建并全量建索引
// // //         if (build_index_and_chain(log_path, idx_path, &lines, chain)!=0){
// // //             trigger_alarm("Initial full scan failed (maybe log corrupted)!");
// // //             diee("initial build index failed");
// // //         }
// // //     }else{
// // //         // 已有 idx，则先验证是否与当前日志匹配（保证不会带病启动）
// // //         // 简做：重新全量 build 到临时文件再对比；也可以逐行比对。
// // //         char *tmpidx=NULL; asprintf(&tmpidx, "%s.tmp", idx_path);
// // //         unsigned long long tlines=0; unsigned char tchain[32];
// // //         if (build_index_and_chain(log_path, tmpidx, &tlines, tchain)!=0){
// // //             trigger_alarm("Rebuild index for check failed!");
// // //             diee("rebuild index failed");
// // //         }
// // //         // 对比 tmpidx 的 sm3 与旧 idx 的 sm3
// // //         char sm3_old[65], sm3_new[65];
// // //         if (sm3_file_hex(idx_path, sm3_old)!=0 || sm3_file_hex(tmpidx, sm3_new)!=0){
// // //             unlink(tmpidx);
// // //             trigger_alarm("SM3 on idx files failed!");
// // //             diee("sm3 idx failed");
// // //         }
// // //         if (strcmp(sm3_old, sm3_new)!=0){
// // //             unlink(tmpidx);
// // //             trigger_alarm("Existing idx does not match current log: suspect tampering!");
// // //             diee("idx/log mismatch");
// // //         }
// // //         // 一致，就用 tmpidx 里的 lines/chain 覆盖读取（以保证后续增量接续）
// // //         lines = tlines;
// // //         memcpy(chain, tchain, 32);
// // //         // 用 tmp 取代旧 idx （或直接删除 tmp 保持旧 idx 不变）
// // //         unlink(idx_path);
// // //         if (rename(tmpidx, idx_path)!=0){
// // //             free(tmpidx);
// // //             trigger_alarm("rename tmp idx failed!");
// // //             diee("rename failed");
// // //         }
// // //         free(tmpidx);
// // //     }

// // //     // 计算 index_sm3 并写 seal
// // //     char idx_sm3_hex[65];
// // //     if (sm3_file_hex(idx_path, idx_sm3_hex)!=0) diee("sm3 idx failed 2");
// // //     if (write_seal(log_path, lines, chain, idx_sm3_hex, pkey, cert)!=0) diee("write seal failed");

// // //     // Now 进入监听 append 模式
// // //     int ifd = inotify_init1(IN_NONBLOCK);
// // //     if (ifd<0) die("inotify_init1");
// // //     int wd = inotify_add_watch(ifd, log_path, IN_MODIFY|IN_MOVE_SELF|IN_ATTRIB);
// // //     if (wd<0) die("inotify_add_watch");

// // //     // 记录当前偏移，开始追尾
// // //     unsigned long long offset = 0;
// // //     {
// // //         FILE *lf=fopen(log_path,"rb"); if(lf){ fseeko(lf,0,SEEK_END); offset = ftello(lf); fclose(lf); }
// // //     }
// // //     fprintf(stderr, "[INFO] audit-seal-daemon start. Watching %s ...\n", log_path);

// // //     for (;;){
// // //         char buf[4096];
// // //         ssize_t n = read(ifd, buf, sizeof(buf));
// // //         if (n <= 0){ usleep(200*1000); continue; }

// // //         for (char *p = buf; p < buf+n; ){
// // //             struct inotify_event *ev = (struct inotify_event*)p;
// // //             if (ev->mask & IN_MODIFY){
// // //                 // 有新日志行写入 -> 读取追加的内容进行索引与链值更新，并重新写 seal。
// // //                 if (append_index_and_chain(log_path, idx_path, &lines, chain, &offset)!=0){
// // //                     trigger_alarm("append index failed: maybe file truncated or modified!");
// // //                     // 若希望出现错误就退出，可 die；或继续重建。
// // //                 }else{
// // //                     if (sm3_file_hex(idx_path, idx_sm3_hex)==0){
// // //                         if (write_seal(log_path, lines, chain, idx_sm3_hex, pkey, cert)!=0){
// // //                             trigger_alarm("update seal failed");
// // //                         }
// // //                     }
// // //                 }
// // //             }
// // //             if (ev->mask & IN_MOVE_SELF){
// // //                 trigger_alarm("log file moved (rotation) – you may need to restart daemon or relink.");
// // //                 // 简版：退出让 watchdog / systemd 重新拉起并绑定新路径
// // //                 goto out;
// // //             }
// // //             if (ev->mask & IN_ATTRIB){
// // //                 // 属性改变（如 chattr）不处理
// // //             }
// // //             p += sizeof(struct inotify_event) + ev->len;
// // //         }
// // //     }

// // // out:
// // //     close(ifd);
// // //     EVP_PKEY_free(pkey); X509_free(cert); gm_crypto_cleanup();
// // //     free(idx_path);
// // //     return 0;
// // // }

// /* audit-seal-daemon.c
//    功能：
//    - 后台运行
//    - 监控指定日志路径（file_path）
//    - 维护 index/seal，检测篡改
//    - 自动重绑定目录/文件（处理轮转）
//    - 触发报警（调用 trigger_alarm）
// */

// #define _GNU_SOURCE
// #include <stdio.h>
// #include <stdlib.h>
// #include <unistd.h>
// #include <sys/inotify.h>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <sys/file.h>
// #include <fcntl.h>
// #include <string.h>
// #include <errno.h>
// #include <limits.h>
// #include <signal.h>
// #include <time.h>

// #include "alarm.c"               /* 你的 trigger_alarm 实现 */
// #include "../../lib/gm_crypto.h" /* 如果你想在进程内直接 reseal 可以用 */

// #define LOGDIR "/var/log/audit-gm"
// #define DAEMON_LOG LOGDIR "/daemon.log"
// #define PIDFILE "/var/run/audit-seal-daemon.pid"

// /* 可配置：audit-seal 可执行程序路径（如果你直接用 system 调用） */
// #define AUDIT_SEAL_BIN "/usr/local/bin/audit-seal" /* 或 /usr/local/bin/audit-seal */

// /* 简单记录 */
// static void log_msg(const char *fmt, ...)
// {
//     va_list ap;
//     va_start(ap, fmt);
//     FILE *f = fopen(DAEMON_LOG, "a");
//     if (f)
//     {
//         time_t t = time(NULL);
//         char tb[64];
//         strftime(tb, sizeof(tb), "%Y-%m-%d %H:%M:%S", localtime(&t));
//         fprintf(f, "[%s] ", tb);
//         vfprintf(f, fmt, ap);
//         fprintf(f, "\n");
//         fclose(f);
//     }
//     va_end(ap);
// }

// /* 守护进程化 */
// static int daemonize(const char *pidfile)
// {
//     pid_t pid = fork();
//     if (pid < 0)
//         return -1;
//     if (pid > 0)
//         exit(0); /* parent exit */

//     if (setsid() < 0)
//         return -1;
//     signal(SIGCHLD, SIG_IGN);
//     signal(SIGHUP, SIG_IGN);

//     pid = fork();
//     if (pid < 0)
//         return -1;
//     if (pid > 0)
//         exit(0);

//     umask(0);
//     chdir("/");

//     /* close std fds */
//     close(STDIN_FILENO);
//     close(STDOUT_FILENO);
//     close(STDERR_FILENO);

//     /* 写 pid file */
//     if (pidfile)
//     {
//         FILE *f = fopen(pidfile, "w");
//         if (f)
//         {
//             fprintf(f, "%d\n", getpid());
//             fclose(f);
//         }
//     }
//     return 0;
// }

// /* helper: try to (re)generate .seal by calling external audit-seal program */
// static int call_audit_seal_bin(const char *file_path)
// {
//     char cmd[PATH_MAX * 2];
//     /* use full path to audit-seal if installed; here we assume AUDIT_SEAL_BIN works */
//     snprintf(cmd, sizeof(cmd), "%s \"%s\"", AUDIT_SEAL_BIN, file_path);
//     log_msg("Calling reseal: %s", cmd);
//     int rc = system(cmd);
//     if (rc != 0)
//     {
//         log_msg("audit-seal returned %d", rc);
//         return -1;
//     }
//     return 0;
// }

// /* try reopen target path and reattach watchers (return new wd) */
// static int reopen_and_add_watch(int inotify_fd, const char *file_path)
// {
//     /* attempt to add watch on file path: on success return wd >= 0 */
//     int wd = inotify_add_watch(inotify_fd, file_path,
//                                IN_MODIFY | IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MOVE_SELF | IN_ATTRIB);
//     return wd;
// }

// int main(int argc, char **argv)
// {
//     if (argc != 2)
//     {
//         fprintf(stderr, "Usage: %s /path/to/audit.log\n", argv[0]);
//         return 1;
//     }
//     const char *file_path = argv[1];
//     /* ensure logdir exists */
//     mkdir(LOGDIR, 0755);

//     /* daemonize (后台运行) */
//     // if (daemonize(PIDFILE) != 0)
//     // {
//     //     /* daemonize failed -> fallback to foreground but still usable */
//     //     /* For debug you can skip daemonizing */
//     // }

//     log_msg("Running in foreground mode (systemd supervises).");

//     log_msg("audit-seal-daemon start. Watching %s ...", file_path);

//     /* inotify init */
//     int inotify_fd = inotify_init1(IN_NONBLOCK);
//     if (inotify_fd < 0)
//     {
//         log_msg("inotify_init1 failed: %s", strerror(errno));
//         return 2;
//     }

//     /* watch parent directory for creations/moves (to detect new file after rotation) */
//     char dirpath[PATH_MAX];
//     strncpy(dirpath, file_path, sizeof(dirpath));
//     char *slash = strrchr(dirpath, '/');
//     if (!slash)
//     {
//         log_msg("bad path");
//         return 2;
//     }
//     *slash = '\0';
//     int wd_dir = inotify_add_watch(inotify_fd, dirpath, IN_CREATE | IN_MOVED_TO);
//     if (wd_dir < 0)
//     {
//         log_msg("watch dir failed: %s", strerror(errno));
//     }

//     /* add file watch if exists */
//     int wd_file = -1;
//     wd_file = reopen_and_add_watch(inotify_fd, file_path);
//     if (wd_file >= 0)
//     {
//         log_msg("attached file watch wd=%d", wd_file);
//         /* create initial .seal/.idx if not exists by calling audit-seal */
//         call_audit_seal_bin(file_path);
//     }
//     else
//     {
//         log_msg("file not present yet, will wait for create in dir");
//     }

//     /* main loop */
//     char buf[4096]
//         __attribute__((aligned(__alignof__(struct inotify_event))));
//     while (1)
//     {
//         ssize_t len = read(inotify_fd, buf, sizeof(buf));
//         if (len < 0)
//         {
//             if (errno == EAGAIN)
//             {
//                 /* no events: sleep a bit */
//                 usleep(200000);
//                 continue;
//             }
//             else
//             {
//                 log_msg("inotify read error: %s", strerror(errno));
//                 break;
//             }
//         }
//         ssize_t i = 0;
//         while (i < len)
//         {
//             struct inotify_event *ev = (struct inotify_event *)&buf[i];
//             /* handle dir events */
//             if (ev->wd == wd_dir)
//             {
//                 if ((ev->mask & (IN_CREATE | IN_MOVED_TO)) && ev->len)
//                 {
//                     if (strcmp(ev->name, slash + 1) == 0)
//                     {
//                         /* file created/recreated */
//                         log_msg("Detected new file created: %s (event %x)", ev->name, ev->mask);
//                         if (wd_file >= 0)
//                         {
//                             inotify_rm_watch(inotify_fd, wd_file);
//                             wd_file = -1;
//                         }
//                         wd_file = reopen_and_add_watch(inotify_fd, file_path);
//                         if (wd_file >= 0)
//                         {
//                             log_msg("re-attached file watch after create; reseal/checking...");
//                             /* on creation, compare existing .seal if any */
//                             call_audit_seal_bin(file_path);
//                         }
//                     }
//                 }
//             }
//             else if (ev->wd == wd_file)
//             {
//                 /* file-level events */
//                 if (ev->mask & IN_MODIFY)
//                 {
//                     log_msg("IN_MODIFY detected on %s", file_path);
//                     /* For simplicity: call audit-seal to append/resign.
//                        Optimal: call an incremental append handler that only hashes appended lines and update .idx/.seal atomically.
//                        Here we call existing audit-seal binary which re-computes chain/index and writes .seal (you can optimize later). */
//                     call_audit_seal_bin(file_path);
//                 }
//                 if (ev->mask & IN_CLOSE_WRITE)
//                 {
//                     log_msg("IN_CLOSE_WRITE on %s", file_path);
//                     call_audit_seal_bin(file_path);
//                 }
//                 if (ev->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
//                 {
//                     log_msg("file moved/deleted (likely rotation). Attempt reattach.");
//                     trigger_alarm("log file moved (rotation) detected; attempting reattach");
//                     /* remove old watch */
//                     if (wd_file >= 0)
//                     {
//                         inotify_rm_watch(inotify_fd, wd_file);
//                         wd_file = -1;
//                     }
//                     /* try repeatedly to reattach for a short time (file may appear after rotation) */
//                     int attempts = 0;
//                     while (attempts < 10)
//                     {
//                         wd_file = reopen_and_add_watch(inotify_fd, file_path);
//                         if (wd_file >= 0)
//                         {
//                             log_msg("reattached file watch after rotation");
//                             /* call reseal/check to detect tamper */
//                             call_audit_seal_bin(file_path);
//                             break;
//                         }
//                         attempts++;
//                         sleep(1);
//                     }
//                     if (wd_file < 0)
//                     {
//                         log_msg("failed to reattach file watch after rotation; will keep watching dir for create events");
//                     }
//                 }
//             }
//             else
//             {
//                 /* other watches (if any) */
//             }

//             i += sizeof(struct inotify_event) + ev->len;
//         }
//     }

//     close(inotify_fd);
//     return 0;
// }




